#pragma once

#include <map>

#include "../umlmodel_global.h"
#include "JsonSerializable.h"

namespace uml {

/// <summary>
/// BaseElement
/// Provides basic attributes and operations for UML elements
/// </summary>
class UMLMODEL_EXPORT BaseElement : public JsonSerializable {
public:
    BaseElement();
    explicit BaseElement(const QString& umlType);
    explicit BaseElement(const QString& umlType, const QString& id);

public: // JsonSerializable
    void fromJson(const QJsonObject& json, QStringList& errorList) override;
    void toJson(QJsonObject& json) override;

public:
    QString umlType() const;
    QString guiType() const;
    void setGuiType(const QString& guiType);
    QUuid id() const;
    void setId(const QUuid& id);
    QJsonObject& data();
    QVariant getDataVariant(const QString& key) const;
    QString getDataString(const QString& key, const QString& defaultValue = "")
        const;
    int getDataInt(const QString& key, int defaultValue = 0) const;
    double getDataDouble(const QString& key, double defaultValue = 0.0) const;
    QJsonObject getDataObject(const QString& key) const;
    QJsonArray getDataArray(const QString& key) const;
    bool getDataBool(const QString& key, bool defaultValue = false) const;
    void setData(const QString& key, const QString& value);
    void setData(const QString& key, int value);
    void setData(const QString& key, double value);
    void setData(const QString& key, bool value);
    void setData(const QString& key, QJsonObject& value);
    void setData(const QString& key, QJsonArray& value);

protected: // Fields
    /// <summary>
    /// umlType
    /// For deserialize, this field is used to identify the type of the element,
    /// so the creator knows which class to create.
    /// </summary>
    QString umlType_ = "";

    /// <summary>
    /// guiType
    /// For creating a graphics element, this field is used to identify the type
    /// of the GUI element, so the outer creator knows which graphics class to create.
    /// </summary>
    QString guiType_ = "";

    QUuid id_ = QUuid::createUuid();

    /// <summary>
    /// data
    /// A map to store additional custom data for the element.
    /// For example, the line type of a UML edge.
    /// </summary>
    QJsonObject data_;
};

} // namespace uml
